<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta name="generator" content="Docusaurus v2.0.0-alpha.64">
<title data-react-helmet="true">4. 动态 WebAPI | Fur</title><meta data-react-helmet="true" name="docsearch:version" content="current,latest"><meta data-react-helmet="true" name="twitter:card" content="summary_large_image"><meta data-react-helmet="true" property="og:title" content="4. 动态 WebAPI | Fur"><meta data-react-helmet="true" name="description" content="4.1 什么是控制器"><meta data-react-helmet="true" property="og:description" content="4.1 什么是控制器"><meta data-react-helmet="true" property="og:url" content="https://furos.cn/docs/dynamic-api-controller"><link data-react-helmet="true" rel="shortcut icon" href="/img/favicon.ico"><link data-react-helmet="true" rel="canonical" href="https://furos.cn/docs/dynamic-api-controller"><link rel="stylesheet" href="/styles.5e0af430.css">
<link rel="preload" href="/styles.9b051c7c.js" as="script">
<link rel="preload" href="/runtime~main.1d4f4851.js" as="script">
<link rel="preload" href="/main.6c4d8fc1.js" as="script">
<link rel="preload" href="/1.89dd6df9.js" as="script">
<link rel="preload" href="/2.460be2fd.js" as="script">
<link rel="preload" href="/3.28dfd2e2.js" as="script">
<link rel="preload" href="/1be78505.d8f46f6e.js" as="script">
<link rel="preload" href="/45.ea0e160d.js" as="script">
<link rel="preload" href="/f976f453.c52e3197.js" as="script">
<link rel="preload" href="/17896441.109449bc.js" as="script">
<link rel="preload" href="/0ddd808e.d741f7d1.js" as="script">
</head>
<body>
<script>!function(){function t(t){document.documentElement.setAttribute("data-theme",t)}var e=function(){var t=null;try{t=localStorage.getItem("theme")}catch(t){}return t}();t(null!==e?e:"light")}()</script><div id="__docusaurus">
<nav class="navbar navbar--fixed-top"><div class="navbar__inner"><div class="navbar__items"><div aria-label="Navigation bar toggle" class="navbar__toggle" role="button" tabindex="0"><svg xmlns="http://www.w3.org/2000/svg" width="30" height="30" viewBox="0 0 30 30" role="img" focusable="false"><title>Menu</title><path stroke="currentColor" stroke-linecap="round" stroke-miterlimit="10" stroke-width="2" d="M4 7h22M4 15h22M4 23h22"></path></svg></div><a class="navbar__brand" href="/"><img class="navbar__logo" src="/img/logo.png" alt="Fur Logo"><strong class="navbar__title">Fur</strong></a><a aria-current="page" class="navbar__item navbar__link navbar__link--active" href="/docs/">Next</a><a aria-current="page" class="navbar__item navbar__link navbar__link--active" href="/docs">文档</a><a class="navbar__item navbar__link" href="/blog">博客</a><a target="_blank" rel="noopener noreferrer" class="navbar__item navbar__link">配置</a></div><div class="navbar__items navbar__items--right"><a target="_blank" rel="noopener noreferrer" class="navbar__item navbar__link">视频</a><div class="navbar__item dropdown dropdown--hoverable dropdown--right"><a target="_blank" rel="noopener noreferrer" class="navbar__item navbar__link">工具</a><ul class="dropdown__menu"><li><a target="_blank" rel="noopener noreferrer" class="dropdown__link" position="left">代码生成器</a></li></ul></div><a href="https://gitee.com/monksoul/Fur/board" target="_blank" rel="noopener noreferrer" class="navbar__item navbar__link">看板</a><div class="navbar__item dropdown dropdown--hoverable dropdown--right"><a target="_blank" rel="noopener noreferrer" class="navbar__item navbar__link">仓库</a><ul class="dropdown__menu"><li><a href="https://gitee.com/monksoul/Fur" target="_blank" rel="noopener noreferrer" class="dropdown__link" position="left">Gitee</a></li><li><a href="https://github.com/MonkSoul/Fur" target="_blank" rel="noopener noreferrer" class="dropdown__link" position="left">GitHub</a></li></ul></div><div class="react-toggle react-toggle--disabled displayOnlyInLargeViewport_2aTZ"><div class="react-toggle-track"><div class="react-toggle-track-check"><span class="toggle_BsTx">🌜</span></div><div class="react-toggle-track-x"><span class="toggle_BsTx">🌞</span></div></div><div class="react-toggle-thumb"></div><input type="checkbox" disabled="" aria-label="Dark mode toggle" class="react-toggle-screenreader-only"></div></div></div><div role="presentation" class="navbar-sidebar__backdrop"></div><div class="navbar-sidebar"><div class="navbar-sidebar__brand"><a class="navbar__brand" href="/"><img class="navbar__logo" src="/img/logo.png" alt="Fur Logo"><strong class="navbar__title">Fur</strong></a></div><div class="navbar-sidebar__items"><div class="menu"><ul class="menu__list"><li class="menu__list-item"><a target="_blank" rel="noopener noreferrer" class="menu__link">Versions</a></li><li class="menu__list-item"><a aria-current="page" class="menu__link navbar__link--active" href="/docs">文档</a></li><li class="menu__list-item"><a class="menu__link" href="/blog">博客</a></li><li class="menu__list-item"><a target="_blank" rel="noopener noreferrer" class="menu__link">配置</a></li><li class="menu__list-item"><a target="_blank" rel="noopener noreferrer" class="menu__link">视频</a></li><li class="menu__list-item"><a target="_blank" rel="noopener noreferrer" class="menu__link menu__link--sublist">工具</a><ul class="menu__list"><li class="menu__list-item"><a target="_blank" rel="noopener noreferrer" class="menu__link" position="left">代码生成器</a></li></ul></li><li class="menu__list-item"><a href="https://gitee.com/monksoul/Fur/board" target="_blank" rel="noopener noreferrer" class="menu__link">看板</a></li><li class="menu__list-item"><a target="_blank" rel="noopener noreferrer" class="menu__link menu__link--sublist">仓库</a><ul class="menu__list"><li class="menu__list-item"><a href="https://gitee.com/monksoul/Fur" target="_blank" rel="noopener noreferrer" class="menu__link" position="left">Gitee</a></li><li class="menu__list-item"><a href="https://github.com/MonkSoul/Fur" target="_blank" rel="noopener noreferrer" class="menu__link" position="left">GitHub</a></li></ul></li></ul></div></div></div></nav><div class="main-wrapper"><div class="docPage_2gpo"><div class="docSidebarContainer_3_JD" role="complementary"><div class="sidebar_2urC"><div class="menu menu--responsive menu_5FrY"><button aria-label="Open Menu" aria-haspopup="true" class="button button--secondary button--sm menu__button" type="button"><svg aria-label="Menu" class="sidebarMenuIcon_Dm3K" xmlns="http://www.w3.org/2000/svg" height="24" width="24" viewBox="0 0 32 32" role="img" focusable="false"><title>Menu</title><path stroke="currentColor" stroke-linecap="round" stroke-miterlimit="10" stroke-width="2" d="M4 7h22M4 15h22M4 23h22"></path></svg></button><ul class="menu__list"><li class="menu__list-item menu__list-item--collapsed"><a class="menu__link menu__link--sublist" href="#!">1. 框架介绍</a><ul class="menu__list"><li class="menu__list-item"><a class="menu__link" tabindex="-1" href="/docs/">1.1 介绍</a></li><li class="menu__list-item"><a class="menu__link" tabindex="-1" href="/docs/author">1.2 关于作者</a></li></ul></li><li class="menu__list-item"><a class="menu__link" href="/docs/get-start">2. 一分钟入门</a></li><li class="menu__list-item menu__list-item--collapsed"><a class="menu__link menu__link--sublist" href="#!">3. 配置与选项</a><ul class="menu__list"><li class="menu__list-item"><a class="menu__link" tabindex="-1" href="/docs/configuration">3.1 配置</a></li><li class="menu__list-item"><a class="menu__link" tabindex="-1" href="/docs/options">3.2 选项</a></li></ul></li><li class="menu__list-item"><a aria-current="page" class="menu__link menu__link--active active" href="/docs/dynamic-api-controller">4. 动态 WebAPI</a></li><li class="menu__list-item"><a class="menu__link" href="/docs/specification-document">5. 规范化接口文档</a></li><li class="menu__list-item"><a class="menu__link" href="/docs/friendly-exception">6. 友好异常处理</a></li><li class="menu__list-item"><a class="menu__link" href="/docs/data-validation">7. 数据校验</a></li><li class="menu__list-item menu__list-item--collapsed"><a class="menu__link menu__link--sublist" href="#!">8. 数据库操作指南</a><ul class="menu__list"><li class="menu__list-item"><a class="menu__link" tabindex="-1" href="/docs/dbcontext">8.1 数据库上下文</a></li></ul></li><li class="menu__list-item"><a class="menu__link" href="/docs/dependency-injection">9. 依赖注入/控制反转</a></li><li class="menu__list-item"><a class="menu__link" href="/docs/object-mapper">10. 对象数据映射</a></li><li class="menu__list-item"><a class="menu__link" href="/docs/cache">11. 分布式缓存</a></li><li class="menu__list-item"><a class="menu__link" href="/docs/auth-control">12. 安全鉴权</a></li><li class="menu__list-item"><a class="menu__link" href="/docs/cors">13. CORS 跨域</a></li><li class="menu__list-item"><a class="menu__link" href="/docs/local-language">14. 多语言处理</a></li><li class="menu__list-item"><a class="menu__link" href="/docs/view-engine">15. 视图引擎</a></li><li class="menu__list-item"><a class="menu__link" href="/docs/event-bus">16. 事件总线</a></li><li class="menu__list-item"><a class="menu__link" href="/docs/process-service">17. 进程服务</a></li><li class="menu__list-item"><a class="menu__link" href="/docs/deploy">18. 托管部署</a></li><li class="menu__list-item"><a class="menu__link" href="/docs/signalr">19. 托管部署</a></li><li class="menu__list-item"><a class="menu__link" href="/docs/contribute">20. 贡献指南</a></li></ul></div></div></div><main class="docMainContainer_3EyW"><div class="container padding-vert--lg docItemWrapper_1EkI"><div class="row"><div class="col docItemCol_2ASc"><div class="docItemContainer_3QWW"><article><header><h1 class="docTitle_1Lrw">4. 动态 WebAPI</h1></header><div class="markdown"><h2><a aria-hidden="true" tabindex="-1" class="anchor enhancedAnchor_2cZh" id="41-什么是控制器"></a>4.1 什么是控制器<a aria-hidden="true" tabindex="-1" class="hash-link" href="#41-什么是控制器" title="Direct link to heading">#</a></h2><p>简单来说，控制器是一个承上启下的作用，根据用户输入，执行响应行为（动作方法），同时在行为中调用模型的业务逻辑，返回给用户结果（视图）。</p><img src="/img/kzq.png"><p></p><p>在 <code>ASP.NET Core</code> 中，控制器有两种表现形式：</p><ul><li><code>Mvc</code>（带视图）</li><li><code>WebAPI</code>（RESTful API）</li></ul><div><ul role="tablist" aria-orientation="horizontal" class="tabs"><li role="tab" tabindex="0" aria-selected="true" class="tabs__item tabItem_1w39 tabs__item--active" style="outline:none">Mvc 控制器</li><li role="tab" tabindex="0" aria-selected="false" class="tabs__item tabItem_1w39" style="outline:none">WebAPI 控制器</li></ul><div role="tabpanel" class="margin-vert--md"><div><div class="mdxCodeBlock_1XEh"><div class="codeBlockContent_1u-d"><button type="button" aria-label="Copy code to clipboard" class="copyButton_10dd">Copy</button><div tabindex="0" class="prism-code language-cs codeBlock_3iAC"><div class="codeBlockLines_b7E3" style="color:#bfc7d5;background-color:#292d3e"><div class="token-line docusaurus-highlight-code-line" style="color:#bfc7d5"><span class="token plain">using Microsoft.AspNetCore.Mvc;</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block">
</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">namespace Fur.Web.Entry.Controllers</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">{</span></div><div class="token-line docusaurus-highlight-code-line" style="color:#bfc7d5"><span class="token plain">    public class MvcController : Controller</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    {</span></div><div class="token-line docusaurus-highlight-code-line" style="color:#bfc7d5"><span class="token plain">        public IActionResult Index()</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        {</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">            return View();</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        }</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    }</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">}</span></div></div></div></div></div></div></div></div><p><code>Mvc</code> 控制器和 <code>WebAPI</code> 控制器最大的区别是 <code>WebAPI</code> 控制器不带 <strong>视图</strong> 和通过 <strong>请求谓词和路由地址响应行为</strong>。</p><h2><a aria-hidden="true" tabindex="-1" class="anchor enhancedAnchor_2cZh" id="42-mvc-控制器-约定和缺点"></a>4.2 <code>Mvc 控制器</code> 约定和缺点<a aria-hidden="true" tabindex="-1" class="hash-link" href="#42-mvc-控制器-约定和缺点" title="Direct link to heading">#</a></h2><p>在学习动态 <code>WebAPI</code> 控制器之前，首先了解 <code>ASP.NET Core</code> 中 <code>WebAPI</code> 的一些约定和注意事项。</p><h3><a aria-hidden="true" tabindex="-1" class="anchor enhancedAnchor_2cZh" id="421-webapi-约定"></a>4.2.1 <code>WebAPI</code> 约定<a aria-hidden="true" tabindex="-1" class="hash-link" href="#421-webapi-约定" title="Direct link to heading">#</a></h3><p>在 <code>ASP.NET Core</code> 应用中，一个 <code>WebAPI</code> 控制器需遵循以下约定：</p><ul><li>控制器类<strong>必须继承 <code>ControllerBase</code> 或间接继承</strong></li><li>动作方法<strong>必须贴有 <code>[HttpMethod]</code> 特性，如：<code>[HttpGet]</code></strong></li><li>控制器或动作方法<strong>至少有一个配置 <code>[Route]</code> 特性</strong></li><li>生成 <code>WebAPI</code> 路由地址时会自动去掉控制器名称 <code>Controller</code> 后缀，同时也会去掉动作方法匹配的 <code>HttpVerb</code> 谓词，如 <code>GET，POST，DELETE，PUT</code> 等</li><li><strong>不支持返回非 <code>IEnumerable&lt;T&gt;</code> 泛型对象</strong></li><li><strong>不支持类类型参数在 <code>GET，HEAD</code> 请求下生成 <code>Query</code> 参数</strong></li></ul><p>除了上述约定外，<code>WebAPI</code> 路由地址<strong>基本靠手工完成</strong>，不利于书写，不利于维护，再者，在移动应用对接中难以进行多版本控制。</p><h3><a aria-hidden="true" tabindex="-1" class="anchor enhancedAnchor_2cZh" id="422-net-core-webapi-缺点"></a>4.2.2 <code>.NET Core WebAPI</code> 缺点<a aria-hidden="true" tabindex="-1" class="hash-link" href="#422-net-core-webapi-缺点" title="Direct link to heading">#</a></h3><p>通过上一章节可以看出，<code>ASP.NET Core</code> 应用实现 <code>WebAPI</code> 需要遵循种种约定，而且容易出错。</p><p>除了这些约定，<code>.NET Core WebAPI</code> 有以下缺点：</p><ul><li>路由地址基本靠手工完成</li><li>在现在移动为王的时代，不利于进行多版本控制</li><li>对接 <code>Swagger</code> 文档分组比较复杂</li><li>实现 <code>Policy</code> 策略授权也比较复杂</li><li>不支持控制器热拔插插件化</li><li>难以实现复杂自定义的 <code>RESTful API</code> 风格</li></ul><h2><a aria-hidden="true" tabindex="-1" class="anchor enhancedAnchor_2cZh" id="43-动态-webapi-控制器"></a>4.3 动态 <code>WebAPI</code> 控制器<a aria-hidden="true" tabindex="-1" class="hash-link" href="#43-动态-webapi-控制器" title="Direct link to heading">#</a></h2><p>针对以上 <code>ASP.NET Core</code> 提供的 <code>WebAPI</code> 必须遵循的约定和不可避免的缺点，<code>Fur</code> 框架创造出一种更加灵活创建 <code>WebAPI</code> 控制器的方式。</p><p>这个方式在继承了 <code>ASP.NET Core WebAPI</code> 所有优点，同时进行了大量拓展和优化。优化后的 <code>WebAPI</code> 具有以下优点：</p><ul><li>具备原有的 <code>ControllerBase</code> 所有功能</li><li>支持<strong>任意公开 非静态 非抽象 非泛型类</strong>转控制器</li><li>提供更加灵活方便的 <code>IDynamicApiController</code> 空接口或 <code>[DynamicApiController]</code> 特性替代 <code>ControllerBase</code> 抽象类</li><li>无需手动配置 <code>[HttpMethod]</code> 特性，同时支持一个动作方法多个 <code>HttpVerb</code></li><li>无需手动配置 <code>[Route]</code> 特性，支持更加灵活的配置及自动路由生成</li><li>支持返回泛型接口，泛型类</li><li>和 <code>Swagger</code> 深度结合，提供极其方便的创建 <code>Swagger</code> 分组配置</li><li>支持 <code>Basic Auth，Jwt，ApiKey</code> 等多种权限灵活配置</li><li>支持控制器、动作方法<strong>版本控制</strong>功能</li><li>支持 <code>GET、HEAD</code> 请求自动转换 <code>类类型参数</code></li><li>支持生成 <code>OAS3</code> 接口规范</li></ul><h2><a aria-hidden="true" tabindex="-1" class="anchor enhancedAnchor_2cZh" id="44-动态-webapi-使用"></a>4.4 动态 <code>WebAPI</code> 使用<a aria-hidden="true" tabindex="-1" class="hash-link" href="#44-动态-webapi-使用" title="Direct link to heading">#</a></h2><h3><a aria-hidden="true" tabindex="-1" class="anchor enhancedAnchor_2cZh" id="441-注册动态-webapi-服务"></a>4.4.1 注册动态 <code>WebAPI</code> 服务<a aria-hidden="true" tabindex="-1" class="hash-link" href="#441-注册动态-webapi-服务" title="Direct link to heading">#</a></h3><p>在 <code>Fur</code> 框架中，动态 <code>WebAPI</code> 服务需要在 <code>Fur.Web.Entry/Startup.cs</code> 中注册。如：</p><div class="mdxCodeBlock_1XEh"><div style="color:#bfc7d5;background-color:#292d3e" class="codeBlockTitle_3nn1">Fur.Web.Entry/Startup.cs</div><div class="codeBlockContent_1u-d"><button type="button" aria-label="Copy code to clipboard" class="copyButton_10dd undefined">Copy</button><div tabindex="0" class="prism-code language-cs codeBlock_3iAC codeBlockWithTitle_3QsD"><div class="codeBlockLines_b7E3" style="color:#bfc7d5;background-color:#292d3e"><div class="token-line" style="color:#bfc7d5"><span class="token plain">using Microsoft.AspNetCore.Builder;</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">using Microsoft.AspNetCore.Hosting;</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">using Microsoft.Extensions.Configuration;</span></div><div class="token-line docusaurus-highlight-code-line" style="color:#bfc7d5"><span class="token plain">using Microsoft.Extensions.DependencyInjection;</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block">
</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">namespace Fur.Web.Entry</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">{</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    public class Startup</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    {</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        public Startup(IConfiguration configuration)</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        {</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">            Configuration = configuration;</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        }</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block">
</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        public IConfiguration Configuration { get; }</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block">
</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        public void ConfigureServices(IServiceCollection services)</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        {</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">            services.AddApp();</span></div><div class="token-line docusaurus-highlight-code-line" style="color:#bfc7d5"><span class="token plain">            services.AddControllers()</span></div><div class="token-line docusaurus-highlight-code-line" style="color:#bfc7d5"><span class="token plain">                    .AddDynamicApiControllers();</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">            // Other Codes...</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        }</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block">
</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        {</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">            // Other Codes...</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        }</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    }</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">}</span></div></div></div></div></div><div class="admonition admonition-caution alert alert--warning"><div class="admonition-heading"><h5><span class="admonition-icon"><svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"><path fill-rule="evenodd" d="M8.893 1.5c-.183-.31-.52-.5-.887-.5s-.703.19-.886.5L.138 13.499a.98.98 0 0 0 0 1.001c.193.31.53.501.886.501h13.964c.367 0 .704-.19.877-.5a1.03 1.03 0 0 0 .01-1.002L8.893 1.5zm.133 11.497H6.987v-2.003h2.039v2.003zm0-3.004H6.987V5.987h2.039v4.006z"></path></svg></span>特别注意</h5></div><div class="admonition-content"><p><code>.AddDynamicApiControllers()</code> 必须在 <code>services.AddControllers()</code> 之后注册。</p></div></div><h2><a aria-hidden="true" tabindex="-1" class="anchor enhancedAnchor_2cZh" id="45-第一个例子"></a>4.5 第一个例子<a aria-hidden="true" tabindex="-1" class="hash-link" href="#45-第一个例子" title="Direct link to heading">#</a></h2><p>创建一个 <code>FurAppService</code> 类继承 <code>IDynamicApiController</code> 接口 或 贴 <code>[DynamicApiController]</code> 特性，并在这个类中编写一个 <code>Get</code> 方法。</p><ul><li><strong><code>IDynamicApiController</code> 方式</strong></li></ul><div class="mdxCodeBlock_1XEh"><div class="codeBlockContent_1u-d"><button type="button" aria-label="Copy code to clipboard" class="copyButton_10dd">Copy</button><div tabindex="0" class="prism-code language-cs codeBlock_3iAC"><div class="codeBlockLines_b7E3" style="color:#bfc7d5;background-color:#292d3e"><div class="token-line docusaurus-highlight-code-line" style="color:#bfc7d5"><span class="token plain">using Fur.DynamicApiController;</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block">
</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">namespace Fur.Application</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">{</span></div><div class="token-line docusaurus-highlight-code-line" style="color:#bfc7d5"><span class="token plain">    public class FurAppService : IDynamicApiController</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    {</span></div><div class="token-line docusaurus-highlight-code-line" style="color:#bfc7d5"><span class="token plain">        public string Get()</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        {</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">            return $&quot;Hello {nameof(Fur)}&quot;;</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        }</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    }</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">}</span></div></div></div></div></div><ul><li><strong><code>[DynamicApiController]</code> 方式</strong></li></ul><div class="mdxCodeBlock_1XEh"><div class="codeBlockContent_1u-d"><button type="button" aria-label="Copy code to clipboard" class="copyButton_10dd">Copy</button><div tabindex="0" class="prism-code language-cs codeBlock_3iAC"><div class="codeBlockLines_b7E3" style="color:#bfc7d5;background-color:#292d3e"><div class="token-line docusaurus-highlight-code-line" style="color:#bfc7d5"><span class="token plain">using Fur.DynamicApiController;</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block">
</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">namespace Fur.Application</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">{</span></div><div class="token-line docusaurus-highlight-code-line" style="color:#bfc7d5"><span class="token plain">    [DynamicApiController]</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    public class FurAppService</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    {</span></div><div class="token-line docusaurus-highlight-code-line" style="color:#bfc7d5"><span class="token plain">        public string Get()</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        {</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">            return $&quot;Hello {nameof(Fur)}&quot;;</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        }</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    }</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">}</span></div></div></div></div></div><p>如下图所示，一个 <code>WebAPI</code> 接口就这么生成了。</p><img src="/img/dyglz.gif"><h2><a aria-hidden="true" tabindex="-1" class="anchor enhancedAnchor_2cZh" id="46-动态-webapi-原理解析"></a>4.6 动态 <code>WebAPI</code> 原理解析<a aria-hidden="true" tabindex="-1" class="hash-link" href="#46-动态-webapi-原理解析" title="Direct link to heading">#</a></h2><h3><a aria-hidden="true" tabindex="-1" class="anchor enhancedAnchor_2cZh" id="461-控制器特性提供器"></a>4.6.1 控制器特性提供器<a aria-hidden="true" tabindex="-1" class="hash-link" href="#461-控制器特性提供器" title="Direct link to heading">#</a></h3><p><code>Fur</code> 框架会在应用启动时注册 <code>DynamicApiControllerFeatureProvider</code> 控制器特性提供器，该提供器继承自 <code>ControllerFeatureProvider</code> 类。</p><p>接着重写 <code>bool IsController(TypeInfo typeInfo)</code> 方法，用来标识控制器类型。在 <code>Fur</code> 框架中，<strong>继承自 <code>ControllerBase</code> 类或 <code>IDynamicApiController</code> 接口或 <code>[DynamicApiController]</code> 特性都会被标记为控制器类型。</strong></p><h3><a aria-hidden="true" tabindex="-1" class="anchor enhancedAnchor_2cZh" id="462-应用模型转换器"></a>4.6.2 应用模型转换器<a aria-hidden="true" tabindex="-1" class="hash-link" href="#462-应用模型转换器" title="Direct link to heading">#</a></h3><p><code>Fur</code> 框架同时在应用启动时注册 <code>DynamicApiControllerApplicationModelConvention</code> 应用模型转换器，该转换器继承自 <code>IApplicationModelConvention</code> 接口。</p><p>接着实现 <code>void Apply(ApplicationModel application)</code> 接口方法。在该方法中配置控制器名称、路由、导出可见性及动作方法名称、路由、导出可见性等。</p><p>实际上该方法做的就是按照 <strong><a href="#321-webapi-%E7%BA%A6%E5%AE%9A">WebAPI 约定</a></strong> 提前帮我们配置好路由、请求谓词等信息。避免了手动配置的同时还增加了许多新特性，如<strong>版本控制。</strong></p><h2><a aria-hidden="true" tabindex="-1" class="anchor enhancedAnchor_2cZh" id="47-动态-webapi-配置约定"></a>4.7 动态 <code>WebAPI</code> 配置约定<a aria-hidden="true" tabindex="-1" class="hash-link" href="#47-动态-webapi-配置约定" title="Direct link to heading">#</a></h2><h3><a aria-hidden="true" tabindex="-1" class="anchor enhancedAnchor_2cZh" id="471-控制器默认约定"></a>4.7.1 控制器默认约定<a aria-hidden="true" tabindex="-1" class="hash-link" href="#471-控制器默认约定" title="Direct link to heading">#</a></h3><ul><li>生成控制器名称默认去除以 <code>AppServices，AppService，ApiController，Controller，Services，Service</code> 作为前后缀的字符串。见第一个例子中的 <code>FurAppService -&gt; Fur</code> <strong>支持自定义配置</strong></li><li>控制器名称带 <code>V[0-9_]</code> 结尾的，会自动生成控制器版本号，如 <code>FurAppServiceV2 -&gt; Fur@2</code>，<code>FurAppServiceV1_1_0 -&gt; Fur@1.1.0</code>。<strong>支持版本分隔符配置</strong></li><li>控制名称以 <code>骆驼命名（CamelCase）</code> 会自动切割成多个单词 <code>-</code> 连接。<strong>支持自定义配置</strong></li></ul><h3><a aria-hidden="true" tabindex="-1" class="anchor enhancedAnchor_2cZh" id="472-动作方法默认约定"></a>4.7.2 动作方法默认约定<a aria-hidden="true" tabindex="-1" class="hash-link" href="#472-动作方法默认约定" title="Direct link to heading">#</a></h3><ul><li>生成的动作方法名称默认去除以 <code>Post/Add/Create/Insert/Submit，GetAll/GetList/Get/Find/Fetch/Query/Search，Put/Update，Delete/Remove/Clear，Patch</code> 开头的字符串。<strong>支持自定义配置</strong></li><li>生成的动作方法名称默认去除以 <code>Async</code> 作为前后缀的字符串。<strong>支持自定义配置</strong></li><li>动作方法名称带 <code>V[0-9_]</code> 结尾的，会自动生成动作方法版本号，如 <code>ChangePasswordV2 -&gt; ChangePassword@2</code>，<code>ChangePasswordV1_1_0 -&gt; ChangePassword@1.1.0</code>。<strong>支持版本分隔符配置</strong></li><li>动作方法名称以 <code>骆驼命名（CamelCase）</code> 会自动切割成多个单词 <code>-</code> 连接。<strong>支持自定义配置</strong></li><li>动作方法参数将自动转为小写。<strong>支持自定义配置</strong></li></ul><h3><a aria-hidden="true" tabindex="-1" class="anchor enhancedAnchor_2cZh" id="473-请求谓词默认约定"></a>4.7.3 请求谓词默认约定<a aria-hidden="true" tabindex="-1" class="hash-link" href="#473-请求谓词默认约定" title="Direct link to heading">#</a></h3><ul><li>动作方法名<ul><li>以 <code>Post/Add/Create/Insert/Submit</code> 开头，则添加 <code>[HttpPost]</code> 特性。</li><li>以 <code>GetAll/GetList/Get/Find/Fetch/Query/Search</code> 开头，则添加 <code>[HttpGet]</code> 特性。</li><li>以 <code>Put/Update</code> 开头，则添加 <code>[HttpPut]</code> 特性。</li><li>以 <code>Delete/Remove/Clear</code> 开头，则添加 <code>[HttpDelete]</code> 特性。</li><li>以 <code>Patch</code> 开头，则添加 <code>[HttpPatch]</code> 特性</li><li><strong>支持自定义配置</strong></li></ul></li><li>如果不在上面约定中，则默认添加 <code>[HttpPost]</code> 特性。<strong>支持自定义配置</strong></li></ul><h3><a aria-hidden="true" tabindex="-1" class="anchor enhancedAnchor_2cZh" id="474-路由地址默认约定"></a>4.7.4 路由地址默认约定<a aria-hidden="true" tabindex="-1" class="hash-link" href="#474-路由地址默认约定" title="Direct link to heading">#</a></h3><ul><li>默认以 <code>api</code> 开头。<strong>支持自定义配置</strong></li><li>默认转换为小写路由地址。<strong>支持自定义配置</strong></li><li>生成控制器路由模板格式为：<code>api/前置参数列表/模块名或默认区域名/[controller@版本号]/后置参数列表</code></li><li>生成动作方法路由模板格式为：<code>前置参数列表/模块名/[action@版本号]/后置参数列表</code></li></ul><h3><a aria-hidden="true" tabindex="-1" class="anchor enhancedAnchor_2cZh" id="475-其他约定"></a>4.7.5 其他约定<a aria-hidden="true" tabindex="-1" class="hash-link" href="#475-其他约定" title="Direct link to heading">#</a></h3><ul><li>默认不处理 <code>ControllerBase</code> 控制器类型。<strong>支持自定义配置</strong></li><li>默认不处理 <code>GET，HEAD</code> 请求的引用类型参数。<strong>支持自定义配置</strong></li></ul><h2><a aria-hidden="true" tabindex="-1" class="anchor enhancedAnchor_2cZh" id="48-更多例子"></a>4.8 更多例子<a aria-hidden="true" tabindex="-1" class="hash-link" href="#48-更多例子" title="Direct link to heading">#</a></h2><h3><a aria-hidden="true" tabindex="-1" class="anchor enhancedAnchor_2cZh" id="481-多种请求谓词方法"></a>4.8.1 多种请求谓词方法<a aria-hidden="true" tabindex="-1" class="hash-link" href="#481-多种请求谓词方法" title="Direct link to heading">#</a></h3><div class="mdxCodeBlock_1XEh"><div class="codeBlockContent_1u-d"><button type="button" aria-label="Copy code to clipboard" class="copyButton_10dd">Copy</button><div tabindex="0" class="prism-code language-cs codeBlock_3iAC"><div class="codeBlockLines_b7E3" style="color:#bfc7d5;background-color:#292d3e"><div class="token-line" style="color:#bfc7d5"><span class="token plain">using Fur.DynamicApiController;</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block">
</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">namespace Fur.Application</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">{</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    public class FurAppService : IDynamicApiController</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    {</span></div><div class="token-line docusaurus-highlight-code-line" style="color:#bfc7d5"><span class="token plain">        public string Get()</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        {</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">            return $&quot;GET 请求&quot;;</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        }</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block">
</span></div><div class="token-line docusaurus-highlight-code-line" style="color:#bfc7d5"><span class="token plain">        public string Post()</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        {</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">            return $&quot;POST 请求&quot;;</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        }</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block">
</span></div><div class="token-line docusaurus-highlight-code-line" style="color:#bfc7d5"><span class="token plain">        public string Delete()</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        {</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">            return $&quot;DELETE 请求&quot;;</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        }</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block">
</span></div><div class="token-line docusaurus-highlight-code-line" style="color:#bfc7d5"><span class="token plain">        public string Put()</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        {</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">            return $&quot;PUT 请求&quot;;</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        }</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block">
</span></div><div class="token-line docusaurus-highlight-code-line" style="color:#bfc7d5"><span class="token plain">        public string Patch()</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        {</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">            return $&quot;PATCH 请求&quot;;</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        }</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    }</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">}</span></div></div></div></div></div><p>如下图所示：</p><img src="/img/dgqqwc.png"><h3><a aria-hidden="true" tabindex="-1" class="anchor enhancedAnchor_2cZh" id="482-多个自定义动作方法"></a>4.8.2 多个自定义动作方法<a aria-hidden="true" tabindex="-1" class="hash-link" href="#482-多个自定义动作方法" title="Direct link to heading">#</a></h3><div class="mdxCodeBlock_1XEh"><div class="codeBlockContent_1u-d"><button type="button" aria-label="Copy code to clipboard" class="copyButton_10dd">Copy</button><div tabindex="0" class="prism-code language-cs codeBlock_3iAC"><div class="codeBlockLines_b7E3" style="color:#bfc7d5;background-color:#292d3e"><div class="token-line" style="color:#bfc7d5"><span class="token plain">using Fur.DynamicApiController;</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block">
</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">namespace Fur.Application</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">{</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    public class FurAppService : IDynamicApiController</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    {</span></div><div class="token-line docusaurus-highlight-code-line" style="color:#bfc7d5"><span class="token plain">        public string GetVersion()</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        {</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">            return $&quot;v1.0.0&quot;;</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        }</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block">
</span></div><div class="token-line docusaurus-highlight-code-line" style="color:#bfc7d5"><span class="token plain">        public string ChangeProfile()</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        {</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">            return &quot;修改成功&quot;;</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        }</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block">
</span></div><div class="token-line docusaurus-highlight-code-line" style="color:#bfc7d5"><span class="token plain">        public string DeleteUser()</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        {</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">            return &quot;删除成功&quot;;</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        }</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    }</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">}</span></div></div></div></div></div><p>如下图所示：</p><img src="/img/dzmc.png"><h3><a aria-hidden="true" tabindex="-1" class="anchor enhancedAnchor_2cZh" id="483-带参数动作方法"></a>4.8.3 带参数动作方法<a aria-hidden="true" tabindex="-1" class="hash-link" href="#483-带参数动作方法" title="Direct link to heading">#</a></h3><div class="mdxCodeBlock_1XEh"><div class="codeBlockContent_1u-d"><button type="button" aria-label="Copy code to clipboard" class="copyButton_10dd">Copy</button><div tabindex="0" class="prism-code language-cs codeBlock_3iAC"><div class="codeBlockLines_b7E3" style="color:#bfc7d5;background-color:#292d3e"><div class="token-line" style="color:#bfc7d5"><span class="token plain">using Fur.DynamicApiController;</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block">
</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">namespace Fur.Application</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">{</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    public class FurAppService : IDynamicApiController</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    {</span></div><div class="token-line docusaurus-highlight-code-line" style="color:#bfc7d5"><span class="token plain">        public string GetUser(int id)</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        {</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">            return $&quot;{id}&quot;;</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        }</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block">
</span></div><div class="token-line docusaurus-highlight-code-line" style="color:#bfc7d5"><span class="token plain">        public string GetUser(int id, string name)</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        {</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">            return $&quot;{id} {name}&quot;;</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        }</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block">
</span></div><div class="token-line docusaurus-highlight-code-line" style="color:#bfc7d5"><span class="token plain">        public TestDto Add(TestDto testDto)</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        {</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">            return testDto;</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        }</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    }</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">}</span></div></div></div></div></div><p>如下图所示：</p><img src="/img/dcsff.gif"><h3><a aria-hidden="true" tabindex="-1" class="anchor enhancedAnchor_2cZh" id="485-gethead-类类型参数"></a>4.8.5 <code>GET/HEAD</code> 类类型参数<a aria-hidden="true" tabindex="-1" class="hash-link" href="#485-gethead-类类型参数" title="Direct link to heading">#</a></h3><p>默认情况下，<code>ASP.NET Core</code> 会将 <code>GET/HEAD</code> 请求中的 <code>类类型参数</code> 设置为 <code>[FromBody]</code> 绑定，如：</p><div class="mdxCodeBlock_1XEh"><div class="codeBlockContent_1u-d"><button type="button" aria-label="Copy code to clipboard" class="copyButton_10dd">Copy</button><div tabindex="0" class="prism-code language-cs codeBlock_3iAC"><div class="codeBlockLines_b7E3" style="color:#bfc7d5;background-color:#292d3e"><div class="token-line" style="color:#bfc7d5"><span class="token plain">using Fur.DynamicApiController;</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block">
</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">namespace Fur.Application</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">{</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    public class FurAppService : IDynamicApiController</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    {</span></div><div class="token-line docusaurus-highlight-code-line" style="color:#bfc7d5"><span class="token plain">        public TestDto GetTest(TestDto testDto)</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        {</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">            return testDto;</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        }</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    }</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">}</span></div></div></div></div></div><p>如下图所示：</p><img src="/img/getyycs.png"><p>但是，<code>GET、HEAD</code> 请求不支持 <code>From Body</code> 绑定。所以我们需要转换为 <code>Query</code> 查询参数。</p><p><code>Fur</code> 框架支持以下两种方式配置：</p><div><ul role="tablist" aria-orientation="horizontal" class="tabs"><li role="tab" tabindex="0" aria-selected="true" class="tabs__item tabItem_1w39 tabs__item--active" style="outline:none">[FromQuery] 特性</li><li role="tab" tabindex="0" aria-selected="false" class="tabs__item tabItem_1w39" style="outline:none">配置 DynamicApiControllerSettings</li></ul><div role="tabpanel" class="margin-vert--md"><div><div class="mdxCodeBlock_1XEh"><div class="codeBlockContent_1u-d"><button type="button" aria-label="Copy code to clipboard" class="copyButton_10dd">Copy</button><div tabindex="0" class="prism-code language-cs codeBlock_3iAC"><div class="codeBlockLines_b7E3" style="color:#bfc7d5;background-color:#292d3e"><div class="token-line" style="color:#bfc7d5"><span class="token plain">using Fur.DynamicApiController;</span></div><div class="token-line docusaurus-highlight-code-line" style="color:#bfc7d5"><span class="token plain">using Microsoft.AspNetCore.Mvc;</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block">
</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">namespace Fur.Application</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">{</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    public class FurAppService : IDynamicApiController</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    {</span></div><div class="token-line docusaurus-highlight-code-line" style="color:#bfc7d5"><span class="token plain">        public TestDto GetTest([FromQuery] TestDto testDto)</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        {</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">            return testDto;</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        }</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    }</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">}</span></div></div></div></div></div></div></div></div><p>如下图所示：</p><img src="/img/modeltoquery.png"><h3><a aria-hidden="true" tabindex="-1" class="anchor enhancedAnchor_2cZh" id="486-自定义参数位置"></a>4.8.6 自定义参数位置<a aria-hidden="true" tabindex="-1" class="hash-link" href="#486-自定义参数位置" title="Direct link to heading">#</a></h3><p><code>Fur</code> 框架提供了非常方便的自定义参数位置的特性 <code>[ApiSeat]</code>，通过 <code>[ApiSeat]</code> 可配置参数位置，支持以下四种位置：</p><ul><li><code>ApiSeats.ControllerStart</code>：控制器之前</li><li><code>ApiSeats.ControllerEnd</code>：控制器之后</li><li><code>ApiSeats.ActionStart</code>：动作方法之前</li><li><code>ApiSeats.ActionEnd</code>：动作方法之后。<strong>默认值</strong></li></ul><div class="mdxCodeBlock_1XEh"><div class="codeBlockContent_1u-d"><button type="button" aria-label="Copy code to clipboard" class="copyButton_10dd">Copy</button><div tabindex="0" class="prism-code language-cs codeBlock_3iAC"><div class="codeBlockLines_b7E3" style="color:#bfc7d5;background-color:#292d3e"><div class="token-line" style="color:#bfc7d5"><span class="token plain">using Fur.DynamicApiController;</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">using System;</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block">
</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">namespace Fur.Application</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">{</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    public class FurAppService : IDynamicApiController</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    {</span></div><div class="token-line docusaurus-highlight-code-line" style="color:#bfc7d5"><span class="token plain">        // 参数默认为 ApiSeats.ActionEnd</span></div><div class="token-line docusaurus-highlight-code-line" style="color:#bfc7d5"><span class="token plain">        public string RouteSeat(int id, string name)</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        {</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">            return &quot;配置路由参数位置&quot;;</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        }</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block">
</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        public string RouteSeat(</span></div><div class="token-line docusaurus-highlight-code-line" style="color:#bfc7d5"><span class="token plain">            [ApiSeat(ApiSeats.ControllerStart)] int id, // 控制器名称之前</span></div><div class="token-line docusaurus-highlight-code-line" style="color:#bfc7d5"><span class="token plain">            [ApiSeat(ApiSeats.ControllerEnd)] string name, // 控制器名称之后</span></div><div class="token-line docusaurus-highlight-code-line" style="color:#bfc7d5"><span class="token plain">            [ApiSeat(ApiSeats.ControllerEnd)] int age, // 控制器名称之后</span></div><div class="token-line docusaurus-highlight-code-line" style="color:#bfc7d5"><span class="token plain">            [ApiSeat(ApiSeats.ActionStart)] decimal weight, // 动作方法名称之前</span></div><div class="token-line docusaurus-highlight-code-line" style="color:#bfc7d5"><span class="token plain">            [ApiSeat(ApiSeats.ActionStart)] float height, // 动作方法名称之前</span></div><div class="token-line docusaurus-highlight-code-line" style="color:#bfc7d5"><span class="token plain">            [ApiSeat(ApiSeats.ActionEnd)] DateTime birthday) // 动作方法名称之后（默认值）</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        {</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">            return &quot;配置路由参数位置&quot;;</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        }</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    }</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">}</span></div></div></div></div></div><p>如下图所示：</p><img src="/img/cswz.png"><div class="admonition admonition-note alert alert--secondary"><div class="admonition-heading"><h5><span class="admonition-icon"><svg xmlns="http://www.w3.org/2000/svg" width="14" height="16" viewBox="0 0 14 16"><path fill-rule="evenodd" d="M6.3 5.69a.942.942 0 0 1-.28-.7c0-.28.09-.52.28-.7.19-.18.42-.28.7-.28.28 0 .52.09.7.28.18.19.28.42.28.7 0 .28-.09.52-.28.7a1 1 0 0 1-.7.3c-.28 0-.52-.11-.7-.3zM8 7.99c-.02-.25-.11-.48-.31-.69-.2-.19-.42-.3-.69-.31H6c-.27.02-.48.13-.69.31-.2.2-.3.44-.31.69h1v3c.02.27.11.5.31.69.2.2.42.31.69.31h1c.27 0 .48-.11.69-.31.2-.19.3-.42.31-.69H8V7.98v.01zM7 2.3c-3.14 0-5.7 2.54-5.7 5.68 0 3.14 2.56 5.7 5.7 5.7s5.7-2.55 5.7-5.7c0-3.15-2.56-5.69-5.7-5.69v.01zM7 .98c3.86 0 7 3.14 7 7s-3.14 7-7 7-7-3.12-7-7 3.14-7 7-7z"></path></svg></span>温馨提示</h5></div><div class="admonition-content"><p>多个 <strong><code>同位置</code></strong> 配置的参数将按照 <strong><code>定义参数顺序</code></strong> 进行排序。</p></div></div><div class="admonition admonition-caution alert alert--warning"><div class="admonition-heading"><h5><span class="admonition-icon"><svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"><path fill-rule="evenodd" d="M8.893 1.5c-.183-.31-.52-.5-.887-.5s-.703.19-.886.5L.138 13.499a.98.98 0 0 0 0 1.001c.193.31.53.501.886.501h13.964c.367 0 .704-.19.877-.5a1.03 1.03 0 0 0 .01-1.002L8.893 1.5zm.133 11.497H6.987v-2.003h2.039v2.003zm0-3.004H6.987V5.987h2.039v4.006z"></path></svg></span>特别注意</h5></div><div class="admonition-content"><p><code>[ApiSeat]</code> 只能应用于贴了 <code>[FromRoute]</code> 特性的参数或 <code>基元类型、值类型、可空基元类型和可空值类型</code>。</p></div></div><h3><a aria-hidden="true" tabindex="-1" class="anchor enhancedAnchor_2cZh" id="487-自定义请求谓词"></a>4.8.7 自定义请求谓词<a aria-hidden="true" tabindex="-1" class="hash-link" href="#487-自定义请求谓词" title="Direct link to heading">#</a></h3><div class="mdxCodeBlock_1XEh"><div class="codeBlockContent_1u-d"><button type="button" aria-label="Copy code to clipboard" class="copyButton_10dd">Copy</button><div tabindex="0" class="prism-code language-cs codeBlock_3iAC"><div class="codeBlockLines_b7E3" style="color:#bfc7d5;background-color:#292d3e"><div class="token-line" style="color:#bfc7d5"><span class="token plain">using Fur.DynamicApiController;</span></div><div class="token-line docusaurus-highlight-code-line" style="color:#bfc7d5"><span class="token plain">using Microsoft.AspNetCore.Mvc;</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block">
</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">namespace Fur.Application</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">{</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    public class FurAppService : IDynamicApiController</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    {</span></div><div class="token-line docusaurus-highlight-code-line" style="color:#bfc7d5"><span class="token plain">        [HttpPost]</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        public string GetVersion()</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        {</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">            return &quot;1.0.0&quot;;</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        }</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    }</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">}</span></div></div></div></div></div><p>如下图所示：</p><img src="/img/zdywc.png"><h3><a aria-hidden="true" tabindex="-1" class="anchor enhancedAnchor_2cZh" id="488-支持多个谓词"></a>4.8.8 支持多个谓词<a aria-hidden="true" tabindex="-1" class="hash-link" href="#488-支持多个谓词" title="Direct link to heading">#</a></h3><div class="mdxCodeBlock_1XEh"><div class="codeBlockContent_1u-d"><button type="button" aria-label="Copy code to clipboard" class="copyButton_10dd">Copy</button><div tabindex="0" class="prism-code language-cs codeBlock_3iAC"><div class="codeBlockLines_b7E3" style="color:#bfc7d5;background-color:#292d3e"><div class="token-line" style="color:#bfc7d5"><span class="token plain">using Fur.DynamicApiController;</span></div><div class="token-line docusaurus-highlight-code-line" style="color:#bfc7d5"><span class="token plain">using Microsoft.AspNetCore.Mvc;</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block">
</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">namespace Fur.Application</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">{</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    public class FurAppService : IDynamicApiController</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    {</span></div><div class="token-line docusaurus-highlight-code-line" style="color:#bfc7d5"><span class="token plain">        [HttpPost, HttpGet, AcceptVerbs(&quot;PUT&quot;, &quot;DELETE&quot;)]</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        public string GetVersion()</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        {</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">            return &quot;1.0.0&quot;;</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        }</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    }</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">}</span></div></div></div></div></div><p>如下图所示：</p><img src="/img/dgwc.png"><div class="admonition admonition-caution alert alert--warning"><div class="admonition-heading"><h5><span class="admonition-icon"><svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"><path fill-rule="evenodd" d="M8.893 1.5c-.183-.31-.52-.5-.887-.5s-.703.19-.886.5L.138 13.499a.98.98 0 0 0 0 1.001c.193.31.53.501.886.501h13.964c.367 0 .704-.19.877-.5a1.03 1.03 0 0 0 .01-1.002L8.893 1.5zm.133 11.497H6.987v-2.003h2.039v2.003zm0-3.004H6.987V5.987h2.039v4.006z"></path></svg></span>特别注意</h5></div><div class="admonition-content"><p>如果动作方法中含有 <code>类类型参数</code>，且含有 <code>POST/PUT/DELETE</code> 任意请求谓词，那么该参数会自动添加 <code>[FromBody]</code> 参数，即使在 <code>GET/HEAD</code> 请求中不支持。</p></div></div><h3><a aria-hidden="true" tabindex="-1" class="anchor enhancedAnchor_2cZh" id="489-支持自定义路由"></a>4.8.9 支持自定义路由<a aria-hidden="true" tabindex="-1" class="hash-link" href="#489-支持自定义路由" title="Direct link to heading">#</a></h3><p>支持控制器和动作方法自定义路由：</p><div><ul role="tablist" aria-orientation="horizontal" class="tabs"><li role="tab" tabindex="0" aria-selected="true" class="tabs__item tabItem_1w39 tabs__item--active" style="outline:none">自定义控制器路由</li><li role="tab" tabindex="0" aria-selected="false" class="tabs__item tabItem_1w39" style="outline:none">自定义动作方法路由</li><li role="tab" tabindex="0" aria-selected="false" class="tabs__item tabItem_1w39" style="outline:none">同时自定义路由</li><li role="tab" tabindex="0" aria-selected="false" class="tabs__item tabItem_1w39" style="outline:none">谓词自定义路由</li></ul><div role="tabpanel" class="margin-vert--md"><div><div class="mdxCodeBlock_1XEh"><div class="codeBlockContent_1u-d"><button type="button" aria-label="Copy code to clipboard" class="copyButton_10dd">Copy</button><div tabindex="0" class="prism-code language-cs codeBlock_3iAC"><div class="codeBlockLines_b7E3" style="color:#bfc7d5;background-color:#292d3e"><div class="token-line" style="color:#bfc7d5"><span class="token plain">using Fur.DynamicApiController;</span></div><div class="token-line docusaurus-highlight-code-line" style="color:#bfc7d5"><span class="token plain">using Microsoft.AspNetCore.Mvc;</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block">
</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">namespace Fur.Application</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">{</span></div><div class="token-line docusaurus-highlight-code-line" style="color:#bfc7d5"><span class="token plain">    [Route(&quot;customapi/mobile/[controller]&quot;)]</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    public class FurAppService : IDynamicApiController</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    {</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        public string GetVersion()</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        {</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">            return &quot;1.0.0&quot;;</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        }</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    }</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">}</span></div></div></div></div></div><p>如下图所示：</p><img src="/img/kzqrl.png"></div></div></div><div class="admonition admonition-important alert alert--info"><div class="admonition-heading"><h5><span class="admonition-icon"><svg xmlns="http://www.w3.org/2000/svg" width="14" height="16" viewBox="0 0 14 16"><path fill-rule="evenodd" d="M7 2.3c3.14 0 5.7 2.56 5.7 5.7s-2.56 5.7-5.7 5.7A5.71 5.71 0 0 1 1.3 8c0-3.14 2.56-5.7 5.7-5.7zM7 1C3.14 1 0 4.14 0 8s3.14 7 7 7 7-3.14 7-7-3.14-7-7-7zm1 3H6v5h2V4zm0 6H6v2h2v-2z"></path></svg></span>小提示</h5></div><div class="admonition-content"><p>动态方法自定义路由如果以 <strong><code>/</code></strong> 开头，则不会合并控制器路由。</p></div></div><div class="admonition admonition-tip alert alert--success"><div class="admonition-heading"><h5><span class="admonition-icon"><svg xmlns="http://www.w3.org/2000/svg" width="12" height="16" viewBox="0 0 12 16"><path fill-rule="evenodd" d="M6.5 0C3.48 0 1 2.19 1 5c0 .92.55 2.25 1 3 1.34 2.25 1.78 2.78 2 4v1h5v-1c.22-1.22.66-1.75 2-4 .45-.75 1-2.08 1-3 0-2.81-2.48-5-5.5-5zm3.64 7.48c-.25.44-.47.8-.67 1.11-.86 1.41-1.25 2.06-1.45 3.23-.02.05-.02.11-.02.17H5c0-.06 0-.13-.02-.17-.2-1.17-.59-1.83-1.45-3.23-.2-.31-.42-.67-.67-1.11C2.44 6.78 2 5.65 2 5c0-2.2 2.02-4 4.5-4 1.22 0 2.36.42 3.22 1.19C10.55 2.94 11 3.94 11 5c0 .66-.44 1.78-.86 2.48zM4 14h5c-.23 1.14-1.3 2-2.5 2s-2.27-.86-2.5-2z"></path></svg></span>推荐配置</h5></div><div class="admonition-content"><p>自定义路由如果需要用到 <strong>控制器/动作方法名称</strong>，推荐使用 <code>[controller]</code> 或 <code>[action]</code> 占位符，因为该占位符已经自动处理了 <strong>前后缀、版本号、模块名称</strong>等。</p></div></div><h3><a aria-hidden="true" tabindex="-1" class="anchor enhancedAnchor_2cZh" id="4810-多路由随意组合"></a>4.8.10 多路由随意组合<a aria-hidden="true" tabindex="-1" class="hash-link" href="#4810-多路由随意组合" title="Direct link to heading">#</a></h3><p><code>Fur</code> 框架提供了非常灵活的各种路由组合方式，支持一对多，多对多路由组合：</p><div class="mdxCodeBlock_1XEh"><div class="codeBlockContent_1u-d"><button type="button" aria-label="Copy code to clipboard" class="copyButton_10dd">Copy</button><div tabindex="0" class="prism-code language-cs codeBlock_3iAC"><div class="codeBlockLines_b7E3" style="color:#bfc7d5;background-color:#292d3e"><div class="token-line" style="color:#bfc7d5"><span class="token plain">using Fur.DynamicApiController;</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">using Microsoft.AspNetCore.Mvc;</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block">
</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">namespace Fur.Application</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">{</span></div><div class="token-line docusaurus-highlight-code-line" style="color:#bfc7d5"><span class="token plain">    [Route(&quot;api/[controller]&quot;)]</span></div><div class="token-line docusaurus-highlight-code-line" style="color:#bfc7d5"><span class="token plain">    [Route(&quot;api/[controller]/second&quot;)]</span></div><div class="token-line docusaurus-highlight-code-line" style="color:#bfc7d5"><span class="token plain">    [Route(&quot;api/[controller]/three&quot;)]</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    public class FurAppService : IDynamicApiController</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    {</span></div><div class="token-line docusaurus-highlight-code-line" style="color:#bfc7d5"><span class="token plain">        [HttpGet]</span></div><div class="token-line docusaurus-highlight-code-line" style="color:#bfc7d5"><span class="token plain">        [HttpGet(&quot;get/[action]&quot;)]</span></div><div class="token-line docusaurus-highlight-code-line" style="color:#bfc7d5"><span class="token plain">        [HttpPost]</span></div><div class="token-line docusaurus-highlight-code-line" style="color:#bfc7d5"><span class="token plain">        [HttpPost(&quot;post/cus-version&quot;)]</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        public string GetVersion()</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        {</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">            return &quot;1.0.0&quot;;</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        }</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    }</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">}</span></div></div></div></div></div><p>如下图所示：</p><img src="/img/dlrzh.gif"><div class="admonition admonition-caution alert alert--warning"><div class="admonition-heading"><h5><span class="admonition-icon"><svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"><path fill-rule="evenodd" d="M8.893 1.5c-.183-.31-.52-.5-.887-.5s-.703.19-.886.5L.138 13.499a.98.98 0 0 0 0 1.001c.193.31.53.501.886.501h13.964c.367 0 .704-.19.877-.5a1.03 1.03 0 0 0 .01-1.002L8.893 1.5zm.133 11.497H6.987v-2.003h2.039v2.003zm0-3.004H6.987V5.987h2.039v4.006z"></path></svg></span>特别注意</h5></div><div class="admonition-content"><p>动作方法不能同时贴 <code>[Route]</code> 和 <code>[HttpMethod]</code> 特性，只能二取一。</p></div></div><h3><a aria-hidden="true" tabindex="-1" class="anchor enhancedAnchor_2cZh" id="4811-支持版本控制"></a>4.8.11 支持版本控制<a aria-hidden="true" tabindex="-1" class="hash-link" href="#4811-支持版本控制" title="Direct link to heading">#</a></h3><div><ul role="tablist" aria-orientation="horizontal" class="tabs"><li role="tab" tabindex="0" aria-selected="true" class="tabs__item tabItem_1w39 tabs__item--active" style="outline:none">控制器版本</li><li role="tab" tabindex="0" aria-selected="false" class="tabs__item tabItem_1w39" style="outline:none">动作方法版本</li></ul><div role="tabpanel" class="margin-vert--md"><div><div class="mdxCodeBlock_1XEh"><div class="codeBlockContent_1u-d"><button type="button" aria-label="Copy code to clipboard" class="copyButton_10dd">Copy</button><div tabindex="0" class="prism-code language-cs codeBlock_3iAC"><div class="codeBlockLines_b7E3" style="color:#bfc7d5;background-color:#292d3e"><div class="token-line" style="color:#bfc7d5"><span class="token plain">using Fur.DynamicApiController;</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block">
</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">namespace Fur.Application</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">{</span></div><div class="token-line docusaurus-highlight-code-line" style="color:#bfc7d5"><span class="token plain">    public class FurAppServiceV1 : IDynamicApiController</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    {</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        public string Get()</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        {</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">            return nameof(Fur);</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        }</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    }</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block">
</span></div><div class="token-line docusaurus-highlight-code-line" style="color:#bfc7d5"><span class="token plain">    public class FurAppServiceV1_2 : IDynamicApiController</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    {</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        public string Get()</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        {</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">            return nameof(Fur);</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        }</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    }</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block">
</span></div><div class="token-line docusaurus-highlight-code-line" style="color:#bfc7d5"><span class="token plain">    public class FurAppServiceV1_2_1 : IDynamicApiController</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    {</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        public string Get()</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        {</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">            return nameof(Fur);</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        }</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    }</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">}</span></div></div></div></div></div><p>如下图所示：</p><img src="/img/kzqbb.png"></div></div></div><div class="admonition admonition-note alert alert--secondary"><div class="admonition-heading"><h5><span class="admonition-icon"><svg xmlns="http://www.w3.org/2000/svg" width="14" height="16" viewBox="0 0 14 16"><path fill-rule="evenodd" d="M6.3 5.69a.942.942 0 0 1-.28-.7c0-.28.09-.52.28-.7.19-.18.42-.28.7-.28.28 0 .52.09.7.28.18.19.28.42.28.7 0 .28-.09.52-.28.7a1 1 0 0 1-.7.3c-.28 0-.52-.11-.7-.3zM8 7.99c-.02-.25-.11-.48-.31-.69-.2-.19-.42-.3-.69-.31H6c-.27.02-.48.13-.69.31-.2.2-.3.44-.31.69h1v3c.02.27.11.5.31.69.2.2.42.31.69.31h1c.27 0 .48-.11.69-.31.2-.19.3-.42.31-.69H8V7.98v.01zM7 2.3c-3.14 0-5.7 2.54-5.7 5.68 0 3.14 2.56 5.7 5.7 5.7s5.7-2.55 5.7-5.7c0-3.15-2.56-5.69-5.7-5.69v.01zM7 .98c3.86 0 7 3.14 7 7s-3.14 7-7 7-7-3.12-7-7 3.14-7 7-7z"></path></svg></span>版本生成原理</h5></div><div class="admonition-content"><p><strong><code>V[0-9_]</code></strong> 结尾的命名自动解析成版本号，如 <strong><code>FurAppServiceV2 -&gt; Fur@2</code></strong>。</p></div></div><div class="admonition admonition-tip alert alert--success"><div class="admonition-heading"><h5><span class="admonition-icon"><svg xmlns="http://www.w3.org/2000/svg" width="12" height="16" viewBox="0 0 12 16"><path fill-rule="evenodd" d="M6.5 0C3.48 0 1 2.19 1 5c0 .92.55 2.25 1 3 1.34 2.25 1.78 2.78 2 4v1h5v-1c.22-1.22.66-1.75 2-4 .45-.75 1-2.08 1-3 0-2.81-2.48-5-5.5-5zm3.64 7.48c-.25.44-.47.8-.67 1.11-.86 1.41-1.25 2.06-1.45 3.23-.02.05-.02.11-.02.17H5c0-.06 0-.13-.02-.17-.2-1.17-.59-1.83-1.45-3.23-.2-.31-.42-.67-.67-1.11C2.44 6.78 2 5.65 2 5c0-2.2 2.02-4 4.5-4 1.22 0 2.36.42 3.22 1.19C10.55 2.94 11 3.94 11 5c0 .66-.44 1.78-.86 2.48zM4 14h5c-.23 1.14-1.3 2-2.5 2s-2.27-.86-2.5-2z"></path></svg></span>版本复写</h5></div><div class="admonition-content"><p>除了通过特定后缀方式以外，版本还直接通过 <code>[ApiDescriptionSettings]</code> 进行复写。如：</p><div class="mdxCodeBlock_1XEh"><div class="codeBlockContent_1u-d"><button type="button" aria-label="Copy code to clipboard" class="copyButton_10dd">Copy</button><div tabindex="0" class="prism-code language-cs codeBlock_3iAC"><div class="codeBlockLines_b7E3" style="color:#bfc7d5;background-color:#292d3e"><div class="token-line docusaurus-highlight-code-line" style="color:#bfc7d5"><span class="token plain">[ApiDescriptionSettings(Version = &quot;4.0&quot;)]</span></div><div class="token-line docusaurus-highlight-code-line" style="color:#bfc7d5"><span class="token plain">public string GetV1()</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">{</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    return nameof(Fur);</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">}</span></div></div></div></div></div><p>这时，生成版本将采用 <code>4.0</code> 替代 <code>1</code></p></div></div><h3><a aria-hidden="true" tabindex="-1" class="anchor enhancedAnchor_2cZh" id="4812-不公开控制器或动作方法"></a>4.8.12 不公开控制器或动作方法<a aria-hidden="true" tabindex="-1" class="hash-link" href="#4812-不公开控制器或动作方法" title="Direct link to heading">#</a></h3><p>有些时候，我们无需导出某个动作方法或控制器，只需要添加 <code>[ApiDescriptionSettings(false)]</code> 或 <code>[ApiExplorerSettings(IgnoreApi = true)]</code>即可。</p><p>另外动作方法还支持 <code>[NonAction]</code> 标记。</p><div class="admonition admonition-tip alert alert--success"><div class="admonition-heading"><h5><span class="admonition-icon"><svg xmlns="http://www.w3.org/2000/svg" width="12" height="16" viewBox="0 0 12 16"><path fill-rule="evenodd" d="M6.5 0C3.48 0 1 2.19 1 5c0 .92.55 2.25 1 3 1.34 2.25 1.78 2.78 2 4v1h5v-1c.22-1.22.66-1.75 2-4 .45-.75 1-2.08 1-3 0-2.81-2.48-5-5.5-5zm3.64 7.48c-.25.44-.47.8-.67 1.11-.86 1.41-1.25 2.06-1.45 3.23-.02.05-.02.11-.02.17H5c0-.06 0-.13-.02-.17-.2-1.17-.59-1.83-1.45-3.23-.2-.31-.42-.67-.67-1.11C2.44 6.78 2 5.65 2 5c0-2.2 2.02-4 4.5-4 1.22 0 2.36.42 3.22 1.19C10.55 2.94 11 3.94 11 5c0 .66-.44 1.78-.86 2.48zM4 14h5c-.23 1.14-1.3 2-2.5 2s-2.27-.86-2.5-2z"></path></svg></span>推荐使用</h5></div><div class="admonition-content"><p>推荐控制器或动作方法设置不导出使用 <code>[ApiDescriptionSettings(false)]</code> 特性。该特性默认继承自 <code>ApiExplorerSettingsAttribute</code> 类。</p></div></div><h2><a aria-hidden="true" tabindex="-1" class="anchor enhancedAnchor_2cZh" id="49-apidescriptionsettings"></a>4.9 <code>[ApiDescriptionSettings]</code><a aria-hidden="true" tabindex="-1" class="hash-link" href="#49-apidescriptionsettings" title="Direct link to heading">#</a></h2><p>除了上述 <code>ASP.NET Core</code> 提供的配置外，<code>Fur</code> 框架还提供了非常强大且灵活的 <code>[ApiDescriptionSettings]</code> 特性。</p><h3><a aria-hidden="true" tabindex="-1" class="anchor enhancedAnchor_2cZh" id="491-内置配置"></a>4.9.1 内置配置<a aria-hidden="true" tabindex="-1" class="hash-link" href="#491-内置配置" title="Direct link to heading">#</a></h3><ul><li><code>Name</code>：自定义控制器/动作方法名称，<code>string</code>，默认 <code>null</code></li><li><code>KeepName</code>：是否保持原有名称不处理，<code>bool</code>，默认 <code>false</code></li><li><code>SplitCamelCase</code>：切割骆驼命名，<code>bool</code>，默认 <code>true</code></li><li><code>KeepVerb</code>：是否保留动作方法请求谓词，<code>bool</code>，默认 <code>false</code></li><li><code>Enabled</code>：是否导出接口，<code>bool</code>，默认 <code>true</code></li><li><code>Module</code>：模块名，<code>string</code>，默认 <code>null</code></li><li><code>Version</code>：版本号，<code>string</code>，默认 <code>null</code></li><li><code>Groups</code>：接口分组，可结合 <code>Swagger</code> 一起使用，<code>string[]</code>，默认 <code>null</code></li><li><code>Tags</code>：接口标签，可结合 <code>Swagger</code> 一起使用，<code>string[]</code>，默认 <code>null</code></li><li><code>AuthPolicies</code>：授权策略，可结合 <code>授权，JWT</code> 一起使用，<code>string[]</code>，默认 <code>null</code></li></ul><h3><a aria-hidden="true" tabindex="-1" class="anchor enhancedAnchor_2cZh" id="492-name-配置"></a>4.9.2 <code>Name</code> 配置<a aria-hidden="true" tabindex="-1" class="hash-link" href="#492-name-配置" title="Direct link to heading">#</a></h3><p><code>Name</code> 参数可以覆盖动态 <code>WebAPI</code> 自动生成的控制器或动作方法名称。如：</p><div class="mdxCodeBlock_1XEh"><div class="codeBlockContent_1u-d"><button type="button" aria-label="Copy code to clipboard" class="copyButton_10dd">Copy</button><div tabindex="0" class="prism-code language-cs codeBlock_3iAC"><div class="codeBlockLines_b7E3" style="color:#bfc7d5;background-color:#292d3e"><div class="token-line" style="color:#bfc7d5"><span class="token plain">using Fur.DynamicApiController;</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block">
</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">namespace Fur.Application</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">{</span></div><div class="token-line docusaurus-highlight-code-line" style="color:#bfc7d5"><span class="token plain">    [ApiDescriptionSettings(Name = &quot;MyFur&quot;)]</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    public class FurAppService : IDynamicApiController</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    {</span></div><div class="token-line docusaurus-highlight-code-line" style="color:#bfc7d5"><span class="token plain">        [ApiDescriptionSettings(Name = &quot;MyGet&quot;)]</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        public string Get()</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        {</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">            return nameof(Fur);</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        }</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    }</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">}</span></div></div></div></div></div><p>如下图所示：</p><img src="/img/namepz.png"><h3><a aria-hidden="true" tabindex="-1" class="anchor enhancedAnchor_2cZh" id="493-keepname-配置"></a>4.9.3 <code>KeepName</code> 配置<a aria-hidden="true" tabindex="-1" class="hash-link" href="#493-keepname-配置" title="Direct link to heading">#</a></h3><p><code>KeepName</code> 参数可以保留原有的控制器或动作方法名称。如：</p><div class="mdxCodeBlock_1XEh"><div class="codeBlockContent_1u-d"><button type="button" aria-label="Copy code to clipboard" class="copyButton_10dd">Copy</button><div tabindex="0" class="prism-code language-cs codeBlock_3iAC"><div class="codeBlockLines_b7E3" style="color:#bfc7d5;background-color:#292d3e"><div class="token-line" style="color:#bfc7d5"><span class="token plain">using Fur.DynamicApiController;</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block">
</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">namespace Fur.Application</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">{</span></div><div class="token-line docusaurus-highlight-code-line" style="color:#bfc7d5"><span class="token plain">    [ApiDescriptionSettings(KeepName = true)]</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    public class FurAppService : IDynamicApiController</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    {</span></div><div class="token-line docusaurus-highlight-code-line" style="color:#bfc7d5"><span class="token plain">        [ApiDescriptionSettings(KeepName = true)]</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        public string Get()</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        {</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">            return nameof(Fur);</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        }</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    }</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">}</span></div></div></div></div></div><p>如下图所示：</p><img src="/img/keepnamepz.png"><h3><a aria-hidden="true" tabindex="-1" class="anchor enhancedAnchor_2cZh" id="494-splitcamelcase-配置"></a>4.9.4 <code>SplitCamelCase</code> 配置<a aria-hidden="true" tabindex="-1" class="hash-link" href="#494-splitcamelcase-配置" title="Direct link to heading">#</a></h3><p><code>SplitCamelCase</code> 参数默认将骆驼命名切割成多个单词并通过指定 <code>占位符</code> 连接起来。默认 <code>占位符</code> 为 <code>-</code>。默认为 <code>true</code>。如：</p><div class="mdxCodeBlock_1XEh"><div class="codeBlockContent_1u-d"><button type="button" aria-label="Copy code to clipboard" class="copyButton_10dd">Copy</button><div tabindex="0" class="prism-code language-cs codeBlock_3iAC"><div class="codeBlockLines_b7E3" style="color:#bfc7d5;background-color:#292d3e"><div class="token-line" style="color:#bfc7d5"><span class="token plain">using Fur.DynamicApiController;</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block">
</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">namespace Fur.Application</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">{</span></div><div class="token-line docusaurus-highlight-code-line" style="color:#bfc7d5"><span class="token plain">    [ApiDescriptionSettings(SplitCamelCase = false)]</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    public class MyFurAppService : IDynamicApiController</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    {</span></div><div class="token-line docusaurus-highlight-code-line" style="color:#bfc7d5"><span class="token plain">        [ApiDescriptionSettings(SplitCamelCase = true)]</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        public string ChangeUserName()</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        {</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">            return nameof(Fur);</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        }</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    }</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">}</span></div></div></div></div></div><p>如下图所示：</p><img src="/img/splitnamepz.png"><div class="admonition admonition-important alert alert--info"><div class="admonition-heading"><h5><span class="admonition-icon"><svg xmlns="http://www.w3.org/2000/svg" width="14" height="16" viewBox="0 0 14 16"><path fill-rule="evenodd" d="M7 2.3c3.14 0 5.7 2.56 5.7 5.7s-2.56 5.7-5.7 5.7A5.71 5.71 0 0 1 1.3 8c0-3.14 2.56-5.7 5.7-5.7zM7 1C3.14 1 0 4.14 0 8s3.14 7 7 7 7-3.14 7-7-3.14-7-7-7zm1 3H6v5h2V4zm0 6H6v2h2v-2z"></path></svg></span>特别注意</h5></div><div class="admonition-content"><p><code>KeepName</code> 优先级高于 <code>SplitCamelCase</code>，也就是 <code>KeepName</code> 设置为 <code>true</code>，则不会处理 <code>SplitCamelCase</code> 参数。</p></div></div><h3><a aria-hidden="true" tabindex="-1" class="anchor enhancedAnchor_2cZh" id="495-keepverb-配置"></a>4.9.5 <code>KeepVerb</code> 配置<a aria-hidden="true" tabindex="-1" class="hash-link" href="#495-keepverb-配置" title="Direct link to heading">#</a></h3><p><code>KeepVerb</code> 参数作用于动作方法，标识是否保留动作谓词。如：</p><div class="mdxCodeBlock_1XEh"><div class="codeBlockContent_1u-d"><button type="button" aria-label="Copy code to clipboard" class="copyButton_10dd">Copy</button><div tabindex="0" class="prism-code language-cs codeBlock_3iAC"><div class="codeBlockLines_b7E3" style="color:#bfc7d5;background-color:#292d3e"><div class="token-line" style="color:#bfc7d5"><span class="token plain">using Fur.DynamicApiController;</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block">
</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">namespace Fur.Application</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">{</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    public class FurAppService : IDynamicApiController</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    {</span></div><div class="token-line docusaurus-highlight-code-line" style="color:#bfc7d5"><span class="token plain">        [ApiDescriptionSettings(KeepVerb = true)]</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        public string GetVersion()</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        {</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">            return nameof(Fur);</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        }</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    }</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">}</span></div></div></div></div></div><p>如下图所示：</p><img src="/img/keepverbpz.png"><h3><a aria-hidden="true" tabindex="-1" class="anchor enhancedAnchor_2cZh" id="496-enabled-配置"></a>4.9.6 <code>Enabled</code> 配置<a aria-hidden="true" tabindex="-1" class="hash-link" href="#496-enabled-配置" title="Direct link to heading">#</a></h3><p><code>Enabled</code> 参数配置接口是否导出。通常用于动作方法，如果用于控制器实际作用不大。</p><div class="mdxCodeBlock_1XEh"><div class="codeBlockContent_1u-d"><button type="button" aria-label="Copy code to clipboard" class="copyButton_10dd">Copy</button><div tabindex="0" class="prism-code language-cs codeBlock_3iAC"><div class="codeBlockLines_b7E3" style="color:#bfc7d5;background-color:#292d3e"><div class="token-line" style="color:#bfc7d5"><span class="token plain">using Fur.DynamicApiController;</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block">
</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">namespace Fur.Application</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">{</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    public class FurAppService : IDynamicApiController</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    {</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        public string GetVersion()</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        {</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">            return nameof(Fur);</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        }</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block">
</span></div><div class="token-line docusaurus-highlight-code-line" style="color:#bfc7d5"><span class="token plain">        [ApiDescriptionSettings(false)]</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        public string NoExport()</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        {</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">            return nameof(Fur);</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        }</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    }</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">}</span></div></div></div></div></div><p>如下图所示：</p><img src="/img/enablepz.png"><h3><a aria-hidden="true" tabindex="-1" class="anchor enhancedAnchor_2cZh" id="497-module-配置"></a>4.9.7 <code>Module</code> 配置<a aria-hidden="true" tabindex="-1" class="hash-link" href="#497-module-配置" title="Direct link to heading">#</a></h3><p><code>Module</code> 参数可以配置路由分离，类似于 <code>Mvc 区域</code> 的作用。</p><div class="mdxCodeBlock_1XEh"><div class="codeBlockContent_1u-d"><button type="button" aria-label="Copy code to clipboard" class="copyButton_10dd">Copy</button><div tabindex="0" class="prism-code language-cs codeBlock_3iAC"><div class="codeBlockLines_b7E3" style="color:#bfc7d5;background-color:#292d3e"><div class="token-line" style="color:#bfc7d5"><span class="token plain">using Fur.DynamicApiController;</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block">
</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">namespace Fur.Application</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">{</span></div><div class="token-line docusaurus-highlight-code-line" style="color:#bfc7d5"><span class="token plain">    [ApiDescriptionSettings(Module = &quot;mobile&quot;)]</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    public class FurAppService : IDynamicApiController</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    {</span></div><div class="token-line docusaurus-highlight-code-line" style="color:#bfc7d5"><span class="token plain">        [ApiDescriptionSettings(Module = &quot;user&quot;)]</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        public string GetVersion()</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        {</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">            return nameof(Fur);</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        }</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    }</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">}</span></div></div></div></div></div><p>如下图所示：</p><img src="/img/modulepz.png"><h3><a aria-hidden="true" tabindex="-1" class="anchor enhancedAnchor_2cZh" id="498-version-配置"></a>4.9.8 <code>Version</code> 配置<a aria-hidden="true" tabindex="-1" class="hash-link" href="#498-version-配置" title="Direct link to heading">#</a></h3><p><code>Version</code> 参数可以配置接口版本，同时又可以复写特殊版本命名配置。默认版本号分隔符为 <code>@</code>。如：</p><div class="mdxCodeBlock_1XEh"><div class="codeBlockContent_1u-d"><button type="button" aria-label="Copy code to clipboard" class="copyButton_10dd">Copy</button><div tabindex="0" class="prism-code language-cs codeBlock_3iAC"><div class="codeBlockLines_b7E3" style="color:#bfc7d5;background-color:#292d3e"><div class="token-line" style="color:#bfc7d5"><span class="token plain">using Fur.DynamicApiController;</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block">
</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">namespace Fur.Application</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">{</span></div><div class="token-line docusaurus-highlight-code-line" style="color:#bfc7d5"><span class="token plain">    [ApiDescriptionSettings(Version = &quot;1.0&quot;)]</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    public class FurAppService : IDynamicApiController</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    {</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        // V2.0.0 被复写成 V2.1.1</span></div><div class="token-line docusaurus-highlight-code-line" style="color:#bfc7d5"><span class="token plain">        [ApiDescriptionSettings(Version = &quot;2.1.1&quot;)]</span></div><div class="token-line docusaurus-highlight-code-line" style="color:#bfc7d5"><span class="token plain">        public string GetVersionV2_0_0()</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        {</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">            return nameof(Fur);</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        }</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    }</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">}</span></div></div></div></div></div><p>如下图所示：</p><img src="/img/versionpz.png"><h3><a aria-hidden="true" tabindex="-1" class="anchor enhancedAnchor_2cZh" id="499-groups-配置"></a>4.9.9 <code>Groups</code> 配置<a aria-hidden="true" tabindex="-1" class="hash-link" href="#499-groups-配置" title="Direct link to heading">#</a></h3><p><code>Groups</code> 配置主要用于配置 <code>Swagger</code> 分组信息。</p><p>通过配置 <code>Groups</code> 参数可以将<code>控制器和动作方法</code> 进行归类和多个分组直接共享。可通过 <code>[ApiDescriptionSettings(params Groups)]</code> 构造函数传入或指定 <code>Groups</code> 参数配置接口是否导出。通常用于动作方法，如果用于控制器实际作用不大。</p><div class="mdxCodeBlock_1XEh"><div class="codeBlockContent_1u-d"><button type="button" aria-label="Copy code to clipboard" class="copyButton_10dd">Copy</button><div tabindex="0" class="prism-code language-cs codeBlock_3iAC"><div class="codeBlockLines_b7E3" style="color:#bfc7d5;background-color:#292d3e"><div class="token-line" style="color:#bfc7d5"><span class="token plain">using Fur.DynamicApiController;</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block">
</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">namespace Fur.Application</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">{</span></div><div class="token-line docusaurus-highlight-code-line" style="color:#bfc7d5"><span class="token plain">    [ApiDescriptionSettings(&quot;Default&quot;, &quot;Common&quot;)]</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    public class FurAppService : IDynamicApiController</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    {</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        public string Get()</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        {</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">            return nameof(Fur);</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        }</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block">
</span></div><div class="token-line docusaurus-highlight-code-line" style="color:#bfc7d5"><span class="token plain">        [ApiDescriptionSettings(&quot;Custom&quot;)]</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        public int Get(int id)</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        {</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">            return id;</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        }</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    }</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">}</span></div></div></div></div></div><p>如下图所示：</p><img src="/img/dfz.gif"><h3><a aria-hidden="true" tabindex="-1" class="anchor enhancedAnchor_2cZh" id="4910-tag-配置"></a>4.9.10 <code>Tag</code> 配置<a aria-hidden="true" tabindex="-1" class="hash-link" href="#4910-tag-配置" title="Direct link to heading">#</a></h3><p><code>Tag</code> 配置主要用于配置 <code>Swagger</code> 标签分组信息及合并标签。也就是 <code>组中组</code>:</p><div><ul role="tablist" aria-orientation="horizontal" class="tabs"><li role="tab" tabindex="0" aria-selected="true" class="tabs__item tabItem_1w39 tabs__item--active" style="outline:none">标签命名</li><li role="tab" tabindex="0" aria-selected="false" class="tabs__item tabItem_1w39" style="outline:none">合并标签</li></ul><div role="tabpanel" class="margin-vert--md"><div><h4><a aria-hidden="true" tabindex="-1" class="anchor enhancedAnchor_2cZh" id="未贴标签之前"></a>未贴标签之前<a aria-hidden="true" tabindex="-1" class="hash-link" href="#未贴标签之前" title="Direct link to heading">#</a></h4><div class="mdxCodeBlock_1XEh"><div class="codeBlockContent_1u-d"><button type="button" aria-label="Copy code to clipboard" class="copyButton_10dd">Copy</button><div tabindex="0" class="prism-code language-cs codeBlock_3iAC"><div class="codeBlockLines_b7E3" style="color:#bfc7d5;background-color:#292d3e"><div class="token-line" style="color:#bfc7d5"><span class="token plain">using Fur.DynamicApiController;</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block">
</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">namespace Fur.Application</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">{</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    public class FurAppService : IDynamicApiController</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    {</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        public string Get()</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        {</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">            return nameof(Fur);</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        }</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block">
</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        public int Get(int id)</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        {</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">            return id;</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        }</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    }</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block">
</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    public class TestAppService : IDynamicApiController</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    {</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        public string Get()</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        {</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">            return nameof(Fur);</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        }</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block">
</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        public int Get(int id)</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        {</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">            return id;</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        }</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    }</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">}</span></div></div></div></div></div><h4><a aria-hidden="true" tabindex="-1" class="anchor enhancedAnchor_2cZh" id="贴标签之后"></a>贴标签之后<a aria-hidden="true" tabindex="-1" class="hash-link" href="#贴标签之后" title="Direct link to heading">#</a></h4><div class="mdxCodeBlock_1XEh"><div class="codeBlockContent_1u-d"><button type="button" aria-label="Copy code to clipboard" class="copyButton_10dd">Copy</button><div tabindex="0" class="prism-code language-cs codeBlock_3iAC"><div class="codeBlockLines_b7E3" style="color:#bfc7d5;background-color:#292d3e"><div class="token-line" style="color:#bfc7d5"><span class="token plain">using Fur.DynamicApiController;</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block">
</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">namespace Fur.Application</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">{</span></div><div class="token-line docusaurus-highlight-code-line" style="color:#bfc7d5"><span class="token plain">    [ApiDescriptionSettings(Tag = &quot;分组一&quot;)]</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    public class FurAppService : IDynamicApiController</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    {</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        public string Get()</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        {</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">            return nameof(Fur);</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        }</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block">
</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        public int Get(int id)</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        {</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">            return id;</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        }</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    }</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block">
</span></div><div class="token-line docusaurus-highlight-code-line" style="color:#bfc7d5"><span class="token plain">    [ApiDescriptionSettings(Tag = &quot;分组二&quot;)]</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    public class TestAppService : IDynamicApiController</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    {</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        public string Get()</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        {</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">            return nameof(Fur);</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        }</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block">
</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        public int Get(int id)</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        {</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">            return id;</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        }</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    }</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">}</span></div></div></div></div></div><p>如下图所示：</p><img src="/img/tag1.png"></div></div></div><div class="admonition admonition-tip alert alert--success"><div class="admonition-heading"><h5><span class="admonition-icon"><svg xmlns="http://www.w3.org/2000/svg" width="12" height="16" viewBox="0 0 12 16"><path fill-rule="evenodd" d="M6.5 0C3.48 0 1 2.19 1 5c0 .92.55 2.25 1 3 1.34 2.25 1.78 2.78 2 4v1h5v-1c.22-1.22.66-1.75 2-4 .45-.75 1-2.08 1-3 0-2.81-2.48-5-5.5-5zm3.64 7.48c-.25.44-.47.8-.67 1.11-.86 1.41-1.25 2.06-1.45 3.23-.02.05-.02.11-.02.17H5c0-.06 0-.13-.02-.17-.2-1.17-.59-1.83-1.45-3.23-.2-.31-.42-.67-.67-1.11C2.44 6.78 2 5.65 2 5c0-2.2 2.02-4 4.5-4 1.22 0 2.36.42 3.22 1.19C10.55 2.94 11 3.94 11 5c0 .66-.44 1.78-.86 2.48zM4 14h5c-.23 1.14-1.3 2-2.5 2s-2.27-.86-2.5-2z"></path></svg></span>小知识</h5></div><div class="admonition-content"><p>如果 <code>Tag</code> 名字一样，则会自动合并，否则只是命名。</p></div></div><h2><a aria-hidden="true" tabindex="-1" class="anchor enhancedAnchor_2cZh" id="410-dynamicapicontrollersettings-配置"></a>4.10 <code>DynamicApiControllerSettings</code> 配置<a aria-hidden="true" tabindex="-1" class="hash-link" href="#410-dynamicapicontrollersettings-配置" title="Direct link to heading">#</a></h2><p><code>Fur</code> 还提供动态 <code>WebAPI</code> 接口一些全局配置选项，如：</p><ul><li><code>DefaultRoutePrefix</code>：默认路由前缀，<code>string</code>，默认 <code>api</code></li><li><code>DefaultHttpMethod</code>：默认请求谓词，<code>string</code>，默认：<code>POST</code></li><li><code>DefaultModule</code>：默认模块名称（区域），可用作接口版本，<code>string</code>，默认：<code>v1</code></li><li><code>LowercaseRoute</code>：小写路由格式，<code>bool</code>，默认：<code>true</code></li><li><code>KeepVerb</code>：是否保留动作谓词，<code>bool</code>，默认：<code>false</code></li><li><code>CamelCaseSeparator</code>：骆驼命名分隔符，<code>string</code>，默认：<code>-</code></li><li><code>VersionSeparator</code>：版本分隔符，<code>string</code>，默认：<code>@</code></li><li><code>ModelToQuery</code>：<code>GET/HEAD</code> 请求将 <code>类类型参数转查询参数</code>，<code>bool</code>，默认 <code>false</code></li><li><code>SupportedMvcController</code>：是否支持 <code>Mvc Controller</code> 动态配置，<code>bool</code>，默认 <code>false</code></li><li><code>AbandonControllerAffixes</code>：默认去除控制器名称前后缀列表名，<code>string[]</code>，默认：<ul><li><code>AppServices</code></li><li><code>AppService</code></li><li><code>ApiController</code></li><li><code>Controller</code></li><li><code>Services</code></li><li><code>Service</code></li></ul></li><li><code>AbandonActionAffixes</code>：默认去除动作方法名称前后缀列表名，<code>string[]</code>，默认：<ul><li><code>Async</code></li></ul></li></ul><h3><a aria-hidden="true" tabindex="-1" class="anchor enhancedAnchor_2cZh" id="4101-支持-mvc-控制器-动态配置"></a>4.10.1 支持 <code>Mvc 控制器</code> 动态配置<a aria-hidden="true" tabindex="-1" class="hash-link" href="#4101-支持-mvc-控制器-动态配置" title="Direct link to heading">#</a></h3><p>默认情况下，<code>Fur</code> 动态 <code>WebAPI</code> 接口不对 <code>ControllerBase</code> 类型进行任何处理。当然，我们也可以手动启用 <code>ControllerBase</code> 支持。</p><div class="mdxCodeBlock_1XEh"><div style="color:#bfc7d5;background-color:#292d3e" class="codeBlockTitle_3nn1">Fur.Web.Entry/appsettings.json</div><div class="codeBlockContent_1u-d"><button type="button" aria-label="Copy code to clipboard" class="copyButton_10dd undefined">Copy</button><div tabindex="0" class="prism-code language-json codeBlock_3iAC codeBlockWithTitle_3QsD"><div class="codeBlockLines_b7E3" style="color:#bfc7d5;background-color:#292d3e"><div class="token-line" style="color:#bfc7d5"><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span></div><div class="token-line docusaurus-highlight-code-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token property">&quot;AppSettings&quot;</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span></div><div class="token-line docusaurus-highlight-code-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token property">&quot;DynamicApiControllerSettings&quot;</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span></div><div class="token-line docusaurus-highlight-code-line" style="color:#bfc7d5"><span class="token plain">      </span><span class="token property">&quot;SupportedMvcController&quot;</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> </span><span class="token boolean" style="color:rgb(255, 88, 116)">true</span><span class="token plain"></span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span></div></div></div></div></div><p>设置 <code>SupportedMvcController: true</code> 后，<code>Mvc ControllerBase</code> 类型也能和动态 <code>WebAPI</code> 一样的灵活了。代码如下：</p><div class="mdxCodeBlock_1XEh"><div class="codeBlockContent_1u-d"><button type="button" aria-label="Copy code to clipboard" class="copyButton_10dd">Copy</button><div tabindex="0" class="prism-code language-cs codeBlock_3iAC"><div class="codeBlockLines_b7E3" style="color:#bfc7d5;background-color:#292d3e"><div class="token-line" style="color:#bfc7d5"><span class="token plain">using Microsoft.AspNetCore.Mvc;</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block">
</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">namespace Fur.Web.Entry.Controllers</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">{</span></div><div class="token-line docusaurus-highlight-code-line" style="color:#bfc7d5"><span class="token plain">    public class MvcController : ControllerBase</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    {</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        public string Get()</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        {</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">            return nameof(Fur);</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">        }</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">    }</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain">}</span></div><div class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block">
</span></div></div></div></div></div><div class="admonition admonition-warning alert alert--danger"><div class="admonition-heading"><h5><span class="admonition-icon"><svg xmlns="http://www.w3.org/2000/svg" width="12" height="16" viewBox="0 0 12 16"><path fill-rule="evenodd" d="M5.05.31c.81 2.17.41 3.38-.52 4.31C3.55 5.67 1.98 6.45.9 7.98c-1.45 2.05-1.7 6.53 3.53 7.7-2.2-1.16-2.67-4.52-.3-6.61-.61 2.03.53 3.33 1.94 2.86 1.39-.47 2.3.53 2.27 1.67-.02.78-.31 1.44-1.13 1.81 3.42-.59 4.78-3.42 4.78-5.56 0-2.84-2.53-3.22-1.25-5.61-1.52.13-2.03 1.13-1.89 2.75.09 1.08-1.02 1.8-1.86 1.33-.67-.41-.66-1.19-.06-1.78C8.18 5.31 8.68 2.45 5.05.32L5.03.3l.02.01z"></path></svg></span>注意事项</h5></div><div class="admonition-content"><p>启用该配置后，如果 <code>Mvc 控制器</code> 没有任何 <code>[Route]</code> 特性，但是贴了 <code>[ApiController]</code> 特性将会报错。原因是 <code>[ApiController]</code> 特性内部做了路由特性检测。所以建议使用 <code>[ApiDataValidation]</code> 代替。</p><p>查看 <a href="https://github.com/dotnet/aspnetcore/blob/c565386a3ed135560bc2e9017aa54a950b4e35dd/src/Mvc/Mvc.Core/src/ApplicationModels/ApiBehaviorApplicationModelProvider.cs#L90" target="_blank" rel="noopener noreferrer">ASP.NET Core - ApiBehaviorApplicationModelProvider 源码</a></p></div></div><h2><a aria-hidden="true" tabindex="-1" class="anchor enhancedAnchor_2cZh" id="411-反馈与建议"></a>4.11 反馈与建议<a aria-hidden="true" tabindex="-1" class="hash-link" href="#411-反馈与建议" title="Direct link to heading">#</a></h2><div class="admonition admonition-note alert alert--secondary"><div class="admonition-heading"><h5><span class="admonition-icon"><svg xmlns="http://www.w3.org/2000/svg" width="14" height="16" viewBox="0 0 14 16"><path fill-rule="evenodd" d="M6.3 5.69a.942.942 0 0 1-.28-.7c0-.28.09-.52.28-.7.19-.18.42-.28.7-.28.28 0 .52.09.7.28.18.19.28.42.28.7 0 .28-.09.52-.28.7a1 1 0 0 1-.7.3c-.28 0-.52-.11-.7-.3zM8 7.99c-.02-.25-.11-.48-.31-.69-.2-.19-.42-.3-.69-.31H6c-.27.02-.48.13-.69.31-.2.2-.3.44-.31.69h1v3c.02.27.11.5.31.69.2.2.42.31.69.31h1c.27 0 .48-.11.69-.31.2-.19.3-.42.31-.69H8V7.98v.01zM7 2.3c-3.14 0-5.7 2.54-5.7 5.68 0 3.14 2.56 5.7 5.7 5.7s5.7-2.55 5.7-5.7c0-3.15-2.56-5.69-5.7-5.69v.01zM7 .98c3.86 0 7 3.14 7 7s-3.14 7-7 7-7-3.12-7-7 3.14-7 7-7z"></path></svg></span>与我们交流</h5></div><div class="admonition-content"><p>给 Fur 提 <a href="https://gitee.com/monksoul/Fur/issues/new?issue" target="_blank" rel="noopener noreferrer">Issue</a>。</p></div></div></div></article><div class="margin-vert--xl"><div class="row"><div class="col"><a href="https://gitee.com/monksoul/Fur/tree/alpha/docs/docs/dynamic-api-controller.mdx" target="_blank" rel="noreferrer noopener"><svg fill="currentColor" height="1.2em" width="1.2em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 40 40" style="margin-right:0.3em;vertical-align:sub"><g><path d="m34.5 11.7l-3 3.1-6.3-6.3 3.1-3q0.5-0.5 1.2-0.5t1.1 0.5l3.9 3.9q0.5 0.4 0.5 1.1t-0.5 1.2z m-29.5 17.1l18.4-18.5 6.3 6.3-18.4 18.4h-6.3v-6.2z"></path></g></svg>Edit this page</a></div></div></div><div class="margin-vert--lg"><nav class="pagination-nav" aria-label="Blog list page navigation"><div class="pagination-nav__item"><a class="pagination-nav__link" href="/docs/options"><div class="pagination-nav__sublabel">Previous</div><div class="pagination-nav__label">« 3.2 选项</div></a></div><div class="pagination-nav__item pagination-nav__item--next"><a class="pagination-nav__link" href="/docs/specification-document"><div class="pagination-nav__sublabel">Next</div><div class="pagination-nav__label">5. 规范化接口文档 »</div></a></div></nav></div></div></div><div class="col col--3"><div class="tableOfContents_3SO_"><ul class="table-of-contents table-of-contents__left-border"><li><a href="#41-什么是控制器" class="table-of-contents__link">4.1 什么是控制器</a></li><li><a href="#42-mvc-控制器-约定和缺点" class="table-of-contents__link">4.2 <code>Mvc 控制器</code> 约定和缺点</a><ul><li><a href="#421-webapi-约定" class="table-of-contents__link">4.2.1 <code>WebAPI</code> 约定</a></li><li><a href="#422-net-core-webapi-缺点" class="table-of-contents__link">4.2.2 <code>.NET Core WebAPI</code> 缺点</a></li></ul></li><li><a href="#43-动态-webapi-控制器" class="table-of-contents__link">4.3 动态 <code>WebAPI</code> 控制器</a></li><li><a href="#44-动态-webapi-使用" class="table-of-contents__link">4.4 动态 <code>WebAPI</code> 使用</a><ul><li><a href="#441-注册动态-webapi-服务" class="table-of-contents__link">4.4.1 注册动态 <code>WebAPI</code> 服务</a></li></ul></li><li><a href="#45-第一个例子" class="table-of-contents__link">4.5 第一个例子</a></li><li><a href="#46-动态-webapi-原理解析" class="table-of-contents__link">4.6 动态 <code>WebAPI</code> 原理解析</a><ul><li><a href="#461-控制器特性提供器" class="table-of-contents__link">4.6.1 控制器特性提供器</a></li><li><a href="#462-应用模型转换器" class="table-of-contents__link">4.6.2 应用模型转换器</a></li></ul></li><li><a href="#47-动态-webapi-配置约定" class="table-of-contents__link">4.7 动态 <code>WebAPI</code> 配置约定</a><ul><li><a href="#471-控制器默认约定" class="table-of-contents__link">4.7.1 控制器默认约定</a></li><li><a href="#472-动作方法默认约定" class="table-of-contents__link">4.7.2 动作方法默认约定</a></li><li><a href="#473-请求谓词默认约定" class="table-of-contents__link">4.7.3 请求谓词默认约定</a></li><li><a href="#474-路由地址默认约定" class="table-of-contents__link">4.7.4 路由地址默认约定</a></li><li><a href="#475-其他约定" class="table-of-contents__link">4.7.5 其他约定</a></li></ul></li><li><a href="#48-更多例子" class="table-of-contents__link">4.8 更多例子</a><ul><li><a href="#481-多种请求谓词方法" class="table-of-contents__link">4.8.1 多种请求谓词方法</a></li><li><a href="#482-多个自定义动作方法" class="table-of-contents__link">4.8.2 多个自定义动作方法</a></li><li><a href="#483-带参数动作方法" class="table-of-contents__link">4.8.3 带参数动作方法</a></li><li><a href="#485-gethead-类类型参数" class="table-of-contents__link">4.8.5 <code>GET/HEAD</code> 类类型参数</a></li><li><a href="#486-自定义参数位置" class="table-of-contents__link">4.8.6 自定义参数位置</a></li><li><a href="#487-自定义请求谓词" class="table-of-contents__link">4.8.7 自定义请求谓词</a></li><li><a href="#488-支持多个谓词" class="table-of-contents__link">4.8.8 支持多个谓词</a></li><li><a href="#489-支持自定义路由" class="table-of-contents__link">4.8.9 支持自定义路由</a></li><li><a href="#4810-多路由随意组合" class="table-of-contents__link">4.8.10 多路由随意组合</a></li><li><a href="#4811-支持版本控制" class="table-of-contents__link">4.8.11 支持版本控制</a></li><li><a href="#4812-不公开控制器或动作方法" class="table-of-contents__link">4.8.12 不公开控制器或动作方法</a></li></ul></li><li><a href="#49-apidescriptionsettings" class="table-of-contents__link">4.9 <code>[ApiDescriptionSettings]</code></a><ul><li><a href="#491-内置配置" class="table-of-contents__link">4.9.1 内置配置</a></li><li><a href="#492-name-配置" class="table-of-contents__link">4.9.2 <code>Name</code> 配置</a></li><li><a href="#493-keepname-配置" class="table-of-contents__link">4.9.3 <code>KeepName</code> 配置</a></li><li><a href="#494-splitcamelcase-配置" class="table-of-contents__link">4.9.4 <code>SplitCamelCase</code> 配置</a></li><li><a href="#495-keepverb-配置" class="table-of-contents__link">4.9.5 <code>KeepVerb</code> 配置</a></li><li><a href="#496-enabled-配置" class="table-of-contents__link">4.9.6 <code>Enabled</code> 配置</a></li><li><a href="#497-module-配置" class="table-of-contents__link">4.9.7 <code>Module</code> 配置</a></li><li><a href="#498-version-配置" class="table-of-contents__link">4.9.8 <code>Version</code> 配置</a></li><li><a href="#499-groups-配置" class="table-of-contents__link">4.9.9 <code>Groups</code> 配置</a></li><li><a href="#4910-tag-配置" class="table-of-contents__link">4.9.10 <code>Tag</code> 配置</a></li></ul></li><li><a href="#410-dynamicapicontrollersettings-配置" class="table-of-contents__link">4.10 <code>DynamicApiControllerSettings</code> 配置</a><ul><li><a href="#4101-支持-mvc-控制器-动态配置" class="table-of-contents__link">4.10.1 支持 <code>Mvc 控制器</code> 动态配置</a></li></ul></li><li><a href="#411-反馈与建议" class="table-of-contents__link">4.11 反馈与建议</a></li></ul></div></div></div></div></main></div></div><footer class="footer footer--dark"><div class="container"><div class="row footer__links"><div class="col footer__col"><h4 class="footer__title">文档</h4><ul class="footer__items"><li class="footer__item"><a class="footer__link-item" href="/docs">入门</a></li><li class="footer__item"><a class="footer__link-item" href="/docs">指南</a></li></ul></div><div class="col footer__col"><h4 class="footer__title">社区</h4><ul class="footer__items"><li class="footer__item"><a href="https://gitee.com/monksoul/Fur/issues" target="_blank" rel="noopener noreferrer" class="footer__link-item">讨论</a></li><li class="footer__item"><a href="https://gitee.com/monksoul/Fur/board" target="_blank" rel="noopener noreferrer" class="footer__link-item">看板</a></li></ul></div><div class="col footer__col"><h4 class="footer__title">更多</h4><ul class="footer__items"><li class="footer__item"><a class="footer__link-item" href="/blog">博客</a></li><li class="footer__item"><a href="https://gitee.com/monksoul/Fur" target="_blank" rel="noopener noreferrer" class="footer__link-item">仓库</a></li></ul></div></div><div class="text--center"><div>Copyright © 2020 Fur, Baiqian Co.,Ltd.</div></div></div></footer></div>
<script src="/styles.9b051c7c.js"></script>
<script src="/runtime~main.1d4f4851.js"></script>
<script src="/main.6c4d8fc1.js"></script>
<script src="/1.89dd6df9.js"></script>
<script src="/2.460be2fd.js"></script>
<script src="/3.28dfd2e2.js"></script>
<script src="/1be78505.d8f46f6e.js"></script>
<script src="/45.ea0e160d.js"></script>
<script src="/f976f453.c52e3197.js"></script>
<script src="/17896441.109449bc.js"></script>
<script src="/0ddd808e.d741f7d1.js"></script>
</body>
</html>